/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  list.h
 *        \brief  This is a general C language linked list module, two-way mode and general data structure
 *       \author  Lamdonn
 *        \email  Lamdonn@163.com
 *      \version  1.1.0
 *      \license  GPL2
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __list_H
#define __list_H

#include "iterator.h"

/* list type define */
typedef struct 
{
    VOBJECT parent;                     /* parent object */
} LIST, *list_t;

/** 
 *  \brief collation
 *  \param[in] front: address of front data
 *  \param[in] back: address of back data
 *  \return positive: follow, 0-equal, negative-violate
 */
typedef int (*list_sort_rule_t)(void* front, void* back);

/** 
 *  \brief comparison conditions
 *  \param[in] ref: address of referenced data
 *  \param[in] cmp: address of comparative data
 *  \param[in] dsize: size of data
 *  \return 0:non conformance, other: follow
 */
typedef int (*list_condition_t)(void* ref, void* cmp, int dsize);

/** 
 *  \brief element traverse function
 *  \param[in] index: the index of the element in the list
 *  \param[in] data: address of data
 *  \return none
 */
typedef void (*list_traverse_t)(int index, void* data);

/* direction definition */
#define LIST_DIR_H2T                    (1)
#define LIST_DIR_T2H                    (-1)
#define LIST_DIR_UNKNOW                 (0)

/** 
 *  \brief create list
 *  \param[in] dsize: size of list items
 *  \return list handlerr or NULL: fail
 */
list_t list_create(int dsize);

/** 
 *  \brief delete list
 *  \param[in] list: list handler
 *  \return none
 */
void list_delete(list_t list);

/** 
 *  \brief copy list
 *  \param[in] source: source list
 *  \param[in] begin: begin form source list
 *  \param[in] end: end to source list
 *  \return list handlerr or NULL: fail
 */
list_t list_copy(list_t list, int begin, int end);

/** 
 *  \brief insert item to list
 *  \param[in] list: list handler
 *  \param[in] index: the index of list
 *  \param[in] data: address of list item data
 *  \return 1: success or 0: fail
 */
int list_insert(list_t list, int index, void* data);

/** 
 *  \brief insert item to the list with ordered
 *  \param[in] list: list handler
 *  \param[in] data: address of list item data
 *  \param[in] sort_rule: collation
 *  \return 1: success or 0: fail
 */
int list_insert_sort(list_t list, void* data, list_sort_rule_t sort_rule);

/** 
 *  \brief insert item to the head of list
 *  \param[in] list: list handler
 *  \param[in] data: address of list item data
 *  \return 1: success or 0: fail
 */
int list_push_front(list_t list, void* data);

/** 
 *  \brief insert item to the tail of list
 *  \param[in] list: list handler
 *  \param[in] data: address of list item data
 *  \return 1: success or 0: fail
 */
int list_push_back(list_t list, void* data);

/** 
 *  \brief erase item to the tail of list
 *  \param[in] list: list handler
 *  \param[in] begin: begin form list
 *  \param[in] end: end to list
 *  \return 1: success or 0: fail
 */
int list_erase(list_t list, int begin, int end);

/** 
 *  \brief erase item from the head of list
 *  \param[in] list: list handler
 *  \return 1: success or 0: fail
 */
int list_pop_front(list_t list);

/** 
 *  \brief erase item from the tail of list
 *  \param[in] list: list handler
 *  \return 1: success or 0: fail
 */
int list_pop_back(list_t list);

/** 
 *  \brief delete all items in list
 *  \param[in] list: list handler
 *  \return none
 */
void list_clear(list_t list);

/** 
 *  \brief get the address of item data from list
 *  \param[in] list: list handler
 *  \param[in] index: the index of list
 *  \return address of list item data or list_error()
 */
void* list_data(list_t list, int index);

/** 
 *  \brief get item from list
 *  \param[in] list: list handler
 *  \param[in] index: the index of list
 *  \param[out] data: address of list item data
 *  \return 1: success or 0: fail
 */
int list_get(list_t list, int index, void* data);

/** 
 *  \brief alter item of list
 *  \param[in] list: list handler
 *  \param[in] index: the index of list
 *  \param[in] data: address of list item data
 *  \return 1: success or 0: fail
 */
int list_alter(list_t list, int index, void* data);

/** 
 *  \brief find item from list
 *  \param[in] list: list handler
 *  \param[in] data: address of data to find
 *  \param[in] direction: LIST_DIR_H2T or LIST_DIR_T2H
 *  \param[in] which_one: the number of data are looking for, index start at 0
 *  \param[out] out_index: [out] the index of the same data in list
 *  \return address of list item data or list_error(): fail
 */
void* list_find(list_t list, void* data, int direction, int which_one, int *out_index);

/** 
 *  \brief find item from list with condition
 *  \param[in] list: list handler
 *  \param[in] data: address of data to find
 *  \param[in] direction: LIST_DIR_H2T or LIST_DIR_T2H
 *  \param[in] which_one: the number of data are looking for, index start at 0
 *  \param[out] out_index: [out] the index of the same data in list
 *  \param[in] condition: comparison conditions
 *  \return address of list item data or list_error(): fail
 */
void* list_find_if(list_t list, void* data, int direction, int which_one, int *out_index, list_condition_t condition);

/** 
 *  \brief find item from list with additional
 *  \param[in] list: list handler
 *  \param[in] data: address of data to find
 *  \param[in] begin: begin form list
 *  \param[in] end: end to list
 *  \param[in] direction: LIST_DIR_H2T or LIST_DIR_T2H
 *  \param[in] which_one: the number of data are looking for, index start at 0
 *  \param[out] out_index: [out] the index of the same data in list
 *  \param[in] condition: comparison conditions
 *  \return address of list item data or list_error(): fail
 */
void* list_find_ex(list_t list, void* data, int begin, int end, int direction, int which_one, int *out_index, list_condition_t condition);

/** 
 *  \brief remove item from list
 *  \param[in] list: list handler
 *  \param[in] data: address of data to find
 *  \return the count that has been removed
 */
int list_remove(list_t list, void* data);

/** 
 *  \brief remove item from list with condition
 *  \param[in] list: list handler
 *  \param[in] data: address of data to find
 *  \param[in] condition: comparison conditions
 *  \return the count that has been removed
 */
int list_remove_if(list_t list, void* data, list_condition_t condition);

/** 
 *  \brief remove item from list with additional
 *  \param[in] list: list handler
 *  \param[in] data: address of data to find
 *  \param[in] begin: begin form list
 *  \param[in] end: end to list
 *  \param[in] direction: LIST_DIR_H2T or LIST_DIR_T2H
 *  \param[in] size: max count of need to remove, 0-all
 *  \param[in] condition: comparison conditions
 *  \return the count that has been removed
 */
int list_remove_ex(list_t list, void* data, int begin, int end, int direction, int size, list_condition_t condition);

/** 
 *  \brief exchange data between two positions in the list
 *  \param[in] list: list handler
 *  \param[in] index0: position 0 
 *  \param[in] index1: position 1
 *  \return 1: success or 0: fail
 */
int list_switch(list_t list, int index0, int index1);

/** 
 *  \brief swap two list
 *  \param[in] list: list handler
 *  \param[in] swap: list handler of swap
 *  \return none
 */
void list_swap(list_t list, list_t swap);

/** 
 *  \brief reverse list
 *  \param[in] list: list handler
 *  \param[in] begin: begin form list 
 *  \param[in] end: end to list
 *  \return 1: success or 0: fail
 */
int list_reverse(list_t list, int begin, int end);

/** 
 *  \brief splice a list into an other list
 *  \param[in] list_op: target list handler
 *  \param[in] index: target list insert index
 *  \param[in] list_s: source list handler
 *  \param[in] begin: begin form source list
 *  \param[in] end: end to source list
 *  \return 1: success or 0: fail
 */
int list_splice(list_t list, int index, list_t list_s, int begin, int end);

/** 
 *  \brief sort list, default quick algorithm
 *  \param[in] list: list handler
 *  \param[in] begin: begin from list
 *  \param[in] end: end to list
 *  \param[in] sort_rule: collation
 *  \return 1: success or 0: fail
 */
int list_sort(list_t list, int begin, int end, list_sort_rule_t sort_rule);

/** 
 *  \brief get the items count of list
 *  \param[in] list: list handler
 *  \return count of list's item
 */
int list_size(list_t list);

/** 
 *  \brief judge whether the list is empty
 *  \param[in] list: list handler
 *  \return 1: success or 0: fail
 */
int list_empty(list_t list);

/** 
 *  \brief traversal list
 *  \param[in] list: list handler
 *  \param[in] traverse: traverse the function pointer of the item
 *  \return none
 */
void list_traverse(list_t list, int direction, list_traverse_t traverse);

/** 
 *  \brief error return value
 *  \param[in] list: list handler
 *  \return error pointer
 */
void* list_error(list_t list);

/** 
 *  \brief macro definition method for creating list
 *  \param[in] type: tpye of item(e.g int char)
 *  \return list handler
 */
#define list(type)                      list_create(sizeof(type))

/** 
 *  \brief macro definition method for delete list
 *  \param[in] list: list handler
 *  \return none
 */
#define _list(list)                     do{list_delete((list));(list)=NULL;}while(0)

/** 
 *  \brief macro definition method for get front item of list
 *  \param[in] list: list handler
 *  \param[in] type: tpye of item
 *  \param[in] i: index
 *  \return reference to the specified item
 */
#define list_at(list, type, i)          (*(type *)list_data((list),((i)<0?(((vobject_t)list)->size+(i)):(i))))

/** 
 *  \brief macro definition method for get front item of list
 *  \param[in] list: list handler
 *  \param[in] type: tpye of item
 *  \param[in] i: index
 *  \return reference to the specified item
 */
#define list_front(list, type, i)       (*(type *)list_data((list),(i)))

/** 
 *  \brief macro definition method for get back item of list
 *  \param[in] list: list handler
 *  \param[in] type: tpye of item
 *  \param[in] i: index
 *  \return reference to the specified item
 */
#define list_back(list, type, i)        (*(type *)list_data((list),((list)->size-i-1)))

#endif
